package org.iabako.server.dao.business;

import org.iabako.server.dao.JpaDAO;
import org.iabako.shared.entity.business.Client;
import org.iabako.shared.entity.business.CustomField;
import org.iabako.shared.entity.business.CustomFieldListItem;
import org.iabako.shared.entity.business.CustomFieldValue;
import org.iabako.shared.entity.user.Enterprise;
import org.iabako.shared.entity.user.User;
import org.iabako.shared.tools.GenericTools;
import org.springframework.stereotype.Repository;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jose on 22/09/14.
 */

@Repository("customFieldDAO")
public class CustomFieldDAO extends JpaDAO<Long, Client> {


    @Override
    protected String getUniqueNumberVerificationQuery() {
        return null;
    }

    @Override
    protected String getLastNumberQuery() {
        return null;
    }

    public List<CustomField> getCustomFields() {
        User user = getSessionUser();
        return getCustomFields(user.getEnterprise());
    }

    public List<CustomField> getCustomFields(Enterprise enterprise) {
        String query = "SELECT field FROM CustomField field WHERE field.enterprise = :enterprise order by field.position asc";

        enterprise = enterprise.getParentEnterprise() != null ? enterprise.getParentEnterprise() : enterprise;

        return (List<CustomField>) entityManager.createQuery(query).
                setParameter("enterprise", enterprise).getResultList();
    }

    public List<CustomFieldListItem> getCustomFieldsItemValues(CustomField customField) {
        String query = "SELECT item FROM CustomFieldListItem item where item.customField = :customField order by item.label asc";
        return (List<CustomFieldListItem>) entityManager.createQuery(query).setParameter("customField", customField).getResultList();
    }

    public Long getUsagesCustomField(CustomField customField) {
        String query = "SELECT count(value) FROM CustomFieldValue value where value.customField = :customField " +
                "and (value.stringValue is not null or value.integerValue is not null " +
                "or value.doubleValue is not null or value.dateValue is not null " +
                "or value.listItemValue is not null)";
        return (Long) entityManager.createQuery(query).setParameter("customField", customField).getSingleResult();
    }

    public Long getUsagesCustomFieldItemValue(CustomField customField, String itemText) {
        String query = "SELECT count(value) FROM CustomFieldValue value where value.listItemValue = " +
                "(SELECT item FROM CustomFieldListItem item where item.label = :itemText and item.customField = :customField)";
        return (Long) entityManager.createQuery(query).
                setParameter("itemText", itemText).setParameter("customField", customField).getSingleResult();
    }

    public Map<String, Map<CustomField, CustomFieldValue>> getCustomFieldValues(List<String> clientNumbers) {

        Map<String, Map<CustomField, CustomFieldValue>> result = new LinkedHashMap<String, Map<CustomField, CustomFieldValue>>();

        List<CustomField> customFields = getCustomFields();
        if (customFields == null || customFields.isEmpty()) {
            return result;
        }

        String query = "SELECT value FROM CustomFieldValue value where client.number in (:clientNumbers) and client.enterprise =:enterprise";
        List<CustomFieldValue> customFieldValues = (List<CustomFieldValue>) entityManager.createQuery(query)
                .setParameter("clientNumbers", clientNumbers)
                .setParameter("enterprise", getSessionUser().getEnterprise()).getResultList();

        for (CustomFieldValue customFieldValue : customFieldValues) {
            String numberClient = customFieldValue.getClient().getNumber();
            if (result.get(numberClient) == null) {
                result.put(numberClient, new LinkedHashMap<CustomField, CustomFieldValue>());
                for (CustomField customField : customFields) {
                    result.get(numberClient).put(customField, null);
                }
            }
            result.get(numberClient).put(customFieldValue.getCustomField(), customFieldValue);
        }

        return result;
    }

    public void removeCustomListItemByLabels(Map<CustomField, List<String>> customFieldListItemTextDeleted) {
        if (GenericTools.isEmpty(customFieldListItemTextDeleted)) {
            return;
        }
        for (CustomField customField : customFieldListItemTextDeleted.keySet()) {
            List<String> items = customFieldListItemTextDeleted.get(customField);
            //delete CustomFieldValue
            String query = "delete from CustomFieldValue value where value.listItemValue in " +
                    "(SELECT item FROM CustomFieldListItem item where item.label in (:items) and item.customField = :customField)";
            entityManager.createQuery(query).setParameter("items", items).setParameter("customField", customField).executeUpdate();

            //delete CustomFieldListItem
            query = "delete from CustomFieldListItem item where label in (:items) and item.customField = :customField";
            entityManager.createQuery(query).setParameter("items", items).setParameter("customField", customField).executeUpdate();
        }

    }

    public List<CustomField> getCustomCriteriaSearchFields(int limit) {

        User user = getSessionUser();

        String query = "SELECT field FROM CustomField field " +
                "WHERE field.criteriaSearch = true " +
                "AND field.enterprise = :enterprise " +
                "AND field.position < :limit order by field.position asc";

        Enterprise enterprise = user.getEnterprise();
        enterprise = enterprise.getParentEnterprise() != null ? enterprise.getParentEnterprise() : enterprise;

        return (List<CustomField>) entityManager.createQuery(query)
                .setParameter("enterprise", enterprise)
                .setParameter("limit", limit).getResultList();
    }
}
